//
//  main.c
//  Structure
//
//  Created by admin on 2019/7/25.
//  Copyright © 2019 猫爷爷的酱醋茶. All rights reserved.
//

/*
 
 结构体
    声明结构体，只是声明了一个新的数据类型，并没有声明变量，而是声明里面具体是有哪些小的变量组合而成的。
 
1. 语法格式：
    a.声明结构体的同时创建变量
      struct 新类型名称
     {
        ...,
        ...,
        ...
    } 变量名1,变量名2,变量3;
    或者单独创建变量
    struct Student stu;  //这个时候声明变量，才会在内存里面开辟一个空间存储，结构体类型为 struct Student类型。
    代表声明了一个Student的结构体，变量名为stu。
 
    b.匿名结构体只能在声明结构的同时就创建变量
      struct
     {
     ...,
     ...,
     ...
     } 变量名;
 
 2. 结构体的初始化方法
    例：StructrueInitialization();
 
 3. 结构体类型的作用域
    一般情况下通常定义为全局变量。
 
 4. 结构体间的相互赋值是值传递
    拷贝一份赋值给目标结构体中对应的成员变量。
 
 5.结构体数组 例：StructrueInitialization();
    struct 结构体名称 数组名称[数字长度]
    struct Student students[5];
    声明了一个长度为5的数组，数组名为students，元素的类型是struct Student类型。
 
 6. 结构体数组的长度计算 例：StructrueInitialization();
    求出数组占用的总的字节数，除以每个元素占用的字节数
    sizeof(students)/sizeof(struct Student);
 
 7. 结构体指针 例：StructPointer();
    1）格式：
        struct 结构类型名称* 指针名;
 
        struct Student* pStu;
        声明了一个pStu指针变量，这个指针变量的类型是struct Student*.
        这个指针只能指向struct Student类型的变量
 
    2）初始化 - 赋struct Student类型的变量的地址
 
    3）通过指针间接操作变量
       第一种方法：
        (*结构体成员指针名).成员
        (*pStu).name   //因为.的优先级比*高，所以需要用括号
       第二种方式：
        使用箭头来访问 ->
        pStu->name
 
 
 8. 结构体嵌套 例：StructureNesting();
 
 9. 结构体与函数
 
    结构体作为函数参数，直接值传递
 
    结构体作为函数返回值 - 如果需要返回结构体变量的地址，那么就要把这个结构体变量创建在堆区
    例：ReturnStructuerPointer();
 */

#include <stdio.h>
#include <stdlib.h>

struct Student
{
    char *name;
    int studentID;
    int score;
};

struct Date
{
    int year;
    int month;
    int day;
};

struct Person
{
    char *name;
    char *gender;
    float height;
    struct Date birthday;
    
};



//结构体的初始化
void StructrueInitialization(void);

//结构体指针
void StructPointer(void);

//结构体嵌套
void StructureNesting(void);

//返回结构体地址
struct Student* ReturnStructuerPointer(void);

int main(int argc, const char * argv[]) {
    
    struct Student *person = ReturnStructuerPointer();
    
    printf("The person's name is %s,StuID is %d,Score is %d\n",person->name,person->studentID,person->score);
    
    
    return 0;
}

//返回结构体地址
struct Student* ReturnStructuerPointer(void)
{
    struct Student *No86 = calloc(1, sizeof(struct Student));
    
    No86->name = "Maoyeye";
    No86->studentID = 31;
    No86->score = 99;
    
    
    return No86;
}

//结构体嵌套
void StructureNesting(void)
{
    
    struct Person No1 = {"Maoyeye","男",170,{1996,12,24}};
    
    printf("现在出厂的No1的名字叫做%s，身高%.1lf,诞生于%d-%d-%d\n",
           No1.name,
           No1.height,
           No1.birthday.year,
           No1.birthday.month,
           No1.birthday.day
           );
    
    
}


//结构体指针
void StructPointer(void)
{
    struct Student students = {"Jack",18,98};
    struct Student* pStu = &students;
    
    //使用指针简洁操作结构体
    //第一种方式
    (*pStu).name = "Rose";
    (*pStu).studentID = 38;
    (*pStu).score = 99;
    
    //第二种方式
    pStu->name = "Maoyeye";
    pStu->studentID = 37;
    pStu->score = 89;
    
    printf("这位成绩优异的学生是%s，学号是%d,成绩为%d\n让我们一同祝贺！\n",
           students.name,students.studentID,students.score);
    //
}


//结构体的初始化
void StructrueInitialization(void)
{

    
    struct Student No1;
    No1.name = "Lily";
    No1.studentID = 38;
    No1.score = 98;
    
    struct Student No2 = {"Lilei",21,96};
    printf("No2的学生信息:name = %s,stuID = %d,score = %d\n",No2.name,No2.studentID,No2.score);
    
    //部分初始化，其他成员自动初始化为0
    struct Student No3 = {"Jack"};
    printf("No3的学生信息:name = %s,stuID = %d,score = %d\n",No3.name,No3.studentID,No3.score);
    
    //给指定的成员初始化
    struct Student Maoyeye = {.studentID = 37,.score = 94};
    
    
    //结构体数组
    struct Student students[] =
    {
        {"Lily",38,98},
        {"Lilei",21,96},
        {"Jack",19,94},
        
    };
    
    //结构体数组的长度
    int length = sizeof(students)/sizeof(struct Student);
    
    //遍历结构体数组的值
    for (int i = 0; i < length; i++)
    {
        printf
        (
         "学生信息:name = %s,stuID = %d,score = %d\n",
         students[i].name,
         students[i].studentID,
         students[i].score
         );
    }
    
}
